with ada.finalization;

generic
  -- type of the target the pointer is dealing with
  type target_t is private;

  -- handlers invoked on initialization and finalization respectivelys
  target_initialize : access procedure(target : in out target_t) := null;
  target_finalize : access procedure(target : in out target_t) := null;

package ariane.elemental.autoptr is

  type Pointer is new Ada.Finalization.Controlled with private;

    -- returns the targeted object pointer 'p' points to
  function target(p : Pointer) return target_t;

  -- override of equal sign that returns if two pointers are considered equal
  -- in which case they are pointing to the same wrapper/target
  function "="(left, right : Pointer) return boolean;

  -- creates an new instance of target and returns a pointer that points to it
  function create return Pointer;

  -- returns the number of pointers referencing the target pointer p points to
  function numrefs(p : Pointer) return integer;

private

  -- wrapper that wraps around an instance of target
  type wrapper_t is tagged
    record
      target : target_t;
      reference_counter : integer;
    end record;

  -- type of access to wrapper for pointer to point to wrapper
  type wrapper_access is access all wrapper_t;

  -- data definition of pointer type
  type Pointer is new Ada.Finalization.Controlled with
    record
      wrapper : wrapper_access;
    end record;

  -- initializer
  overriding procedure Initialize(p : in out Pointer);

  -- adjuster that is called after assignment of 'p'
  overriding procedure Adjust(p : in out Pointer);

  -- finalizer (destructor) of the pointer type for dealing with referencing
  overriding procedure Finalize(p : in out Pointer);

end ariane.elemental.autoptr;
